package com.zj.base.permission;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;

import com.zj.base.permission.annotations.CheekPermissions;
import com.zj.base.permission.annotations.PermissionProcessUtils;
import com.zj.base.permission.checker.BasePermissionChecker;
import com.zj.base.permission.checker.KITKAT_checker;
import com.zj.base.permission.checker.Lower_checker;
import com.zj.base.permission.checker.M_checker;
import com.zj.base.permission.interfaces.OnPermissionCheckListener;
import com.zj.base.permission.interfaces.OnPermissionDialogCancel;
import com.zj.base.permission.interfaces.OnPermissionDialogFill;
import com.zj.base.utils.ToastUtils;
import com.zj.base.views.BaseLoadingView;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.M;
import static com.zj.base.permission.checker.BasePermissionChecker.PERMISSIONCODE;

/**
 * Created by zhaojie on 2017/10/10.
 * <p>
 * This privilege is used only to generate a correct boot for the user to authorize in the process of use.
 * In the process of actual use, it is suggested that try- catch be used in the code to capture exceptions
 * in order to better fit the permissions detection tools.
 */

@SuppressWarnings("unused")
public final class PermissionTools {

    /**
     * permission,content,cancel,fulfil
     * 需要请求的权限需按此格式进行配置，并在调用权限的地方使用传入这些参数；
     */
    public static String appName;
    public static int triggerActHashCode;
    public static boolean isInit = false;

    public static PermissionTools permissionTools;

    public static void init(Context context) {
        if (!isInit) {
            isInit = true;
            appName = getAppName(context);
        }
    }

    public static PermissionTools get(Activity activity) {
        if (permissionTools == null || triggerActHashCode != activity.hashCode()) {
            permissionTools = new PermissionTools(activity);
            triggerActHashCode = activity.hashCode();
        }
        return permissionTools;
    }

    private static synchronized String getAppName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    context.getPackageName(), 0);
            int labelRes = packageInfo.applicationInfo.labelRes;
            return context.getResources().getString(labelRes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void parseAnnotationPermissionsAndRequst(Class<?> cls, OnPermissionCheckListener listener) {
        final CheekPermissions permission_annotation = PermissionProcessUtils.parseCls(cls, CheekPermissions.class);
        if (permission_annotation != null) {
            String[] at = permission_annotation.value();
            if (at.length > 0) {
                setPermissions(at, permission_annotation.isForce()).checkPermissions(listener);
            }
        } else {
            listener.onSuccess(null);
        }
    }

    private BasePermissionChecker checker;

    private PermissionTools(Activity activity) {
        checker = getChecker(activity);
    }

    public PermissionTools setPermissions(Map<String, Boolean> permissions) {
        if (checker != null) {
            checker.setPermissions(permissions);
        }
        return this;
    }

    public PermissionTools setPermissions(String[] permissionName, boolean[] isForce) {
        Map<String, Boolean> map = new HashMap<>();
        if (permissionName.length != isForce.length) {
            throw new IllegalStateException("the array size of params 1 should same as 2");
        }
        for (int i = 0; i < permissionName.length; i++) {
            map.put(permissionName[i], isForce[i]);
        }
        return setPermissions(map);
    }

    public PermissionTools setPermission(boolean isForce, String... permissions) {
        Map<String, Boolean> map = new HashMap<>();
        for (String permission : permissions) {
            map.put(permission, isForce);
        }
        return setPermissions(map);
    }

    public void checkPermissions(OnPermissionCheckListener listener) {
        checker.setOnPermissionCheckerListener(listener).check();
    }

    public void OverridePositiveClick(OnPermissionDialogFill fill) {
        checker.setOnPermissionDialogFill(fill);
    }

    public void OverridePositiveClick(OnPermissionDialogCancel cancel) {
        checker.setOnPermissionDialogCancel(cancel);
    }

    private BasePermissionChecker getChecker(Activity activity) {
        int version = Build.VERSION.SDK_INT;
        if (version >= M) {
            return new M_checker(activity);
        } else if (version >= KITKAT) {
            return new KITKAT_checker(activity);
        } else {
            return new Lower_checker(activity);
        }
    }

    public void onRequestPermissionsResult(int requestCode, String permissins[], int[] grantResults) {
        if (requestCode == PERMISSIONCODE) {
            if (grantResults.length > 0 && permissins.length > 0) {
                if (grantResults[0] != PackageManager.PERMISSION_GRANTED)
                    if (checker != null)
                        checker.PermissionCache.put(permissins[0], false);
            }
            synchronized (this) {
                if (checker != null)
                    checker.check();
            }
        }
    }

    public void onPermissionActivityResult(int requestCode) {
        if (requestCode == PERMISSIONCODE) {
            synchronized (this) {
                if (checker != null)
                    checker.check();
            }
        }
    }


    public void destroy() {
        if (checker != null) {
            checker.setOnPermissionDialogCancel(null);
            checker.setOnPermissionDialogFill(null);
            checker.setOnPermissionCheckerListener(null);
            checker.clear();
            checker = null;
        }
    }
}
